#ifndef FFMSG_QUEUE_H
#define FFMSG_QUEUE_H

#include"SDL.h"
#include"ffmsg.h"
#include<iostream>

#ifdef __cplusplus
extern "C"
{
// 包含ffmpeg头文件
#include "libavutil/avutil.h"
}
#endif

/// \brief The AVMessage class
/// 消息结构体
///
typedef struct AVMessage {
    int type;//消息类型
    int arg1; //参数1
    int arg2; //参数2
    void *obj; //如果参数1，2还不够，那么多余的信息使用该指针接收
    void (*free_l)(void *obj); // obj对象的回收函数
    struct AVMessage *next; // 指针域，指向下一个消息
}AVMessage;

/// \brief The MessageQueue class
/// 消息队列结构体
///
typedef struct MessageQueue{
    AVMessage *first_msg, *last_msg;//队列中第一条消息和最后一条消息
    int nb_msg;//队列中消息的数量
    int abort_request;//终止信号, 0代表正常运行；1代表停止
    SDL_mutex *mutex;//互斥量
    SDL_cond *cond;//条件变量
    AVMessage *recycle_msg;//回收的消息，消息循环使用，回收已消费的消息——当前版本未使用，后续加入
    int recycle_count;//利用了多少次回收的消息，用于打表测试性能——与开发无关
    int alloc_count;//创建了多少次新消息，用于打表测试性能——与开发无关
}MessageQueue;

// 释放msg的obj资源
void msg_free_obj(AVMessage *msg);
// 私有方法插入队列——真实插入队列的底层调用
int msg_queue_put_private(MessageQueue *q, AVMessage *msg);
// 插入消息——封装了 msg_queue_put_private 方法提供给其他 插入消息的方法 调用
int msg_queue_put(MessageQueue *q, AVMessage *msg);
// 初始化消息
void msg_init_msg(AVMessage *msg);
// 插入简单消息，只有消息类型，不带参数
void msg_queue_put_simple1(MessageQueue *q, int type);
// 插入简单消息，只有消息类型和一个参数
void msg_queue_put_simple2(MessageQueue *q, int type, int arg1);
// 插入简单消息，只有消息类型和两个参数
void msg_queue_put_simple3(MessageQueue *q, int type, int arg1, int arg2);
// 释放obj的回收函数
void msg_obj_free_l(void *obj);
// 插入消息，带消息类型和两个参数和obj
void msg_queue_put_simple4(MessageQueue *q, int type, int arg1, int arg2, void *obj, int obj_len, void (*free_l)(void *obj));
// 消息队列初始化
void msg_queue_init(MessageQueue *q);
// 消息队列flush，清空所有的消息
void msg_queue_flush(MessageQueue *q);
// 消息队列销毁——需要重新init、start启动队列
void msg_queue_destroy(MessageQueue *q);
// 消息队列终止，可以通过start再次启动
void msg_queue_abort(MessageQueue *q);
// 启动消息队列
// 反复调start会怎么样：会删除上一次start的内容，完全重新开始一次播放
void msg_queue_start(MessageQueue *q);
/**
 * @brief msg_queue_get 读取消息
 * return < 0 when abort, return 0 when no msg, return >0 when have msg
 * @param q
 * @param msg
 * @param block 是否阻塞式获取消息，0-非阻塞；1-阻塞
 * @return
 */
int msg_queue_get(MessageQueue *q, AVMessage *msg, int block);
/**
 * @brief msg_queue_remove 将指定的type类型的消息从消息队列中移除
 * @param q
 * @param type
 */
void msg_queue_remove(MessageQueue *q, int type);

#endif // FFMSG_QUEUE_H
